﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class AbstractShapeDrawer : MonoBehaviour
{
    public int GUID;

    MeshFilter meshFilter;
    MeshRenderer meshRenderer;
    Mesh mesh;
    Material material;
    /// <summary>
    /// ring 细致度
    /// </summary>
    public int details = 20;

    List<Vector3> vertices;
    List<Vector2> uv;
    List<Vector3> normals;
    List<int> triangles;

    List<Vector3> temp_vertices;

    Vector3 MiddleLine;

    protected virtual void OnEnable()
    {
        if (meshFilter == null)
        {
            meshFilter = GetComponent<MeshFilter>();
        }
        if (meshRenderer == null)
        {
            meshRenderer = GetComponent<MeshRenderer>();
            material = meshRenderer.material;
        }

    }

    public void RefreshColor(Color color)
    {
        material.SetColor("_Color", color);
    }
    public void Reset()
    {
        if (mesh != null)
        {
            
            mesh.Clear();
            mesh = null;
        }
        gameObject.SetActive(false);
    }
    #region 画三角形
    void DrawTriangle()
    {
        mesh = new Mesh();
        //设置顶点
        mesh.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0) };
        //设置三角形顶点顺序，顺时针设置
        mesh.triangles = new int[] { 0, 1, 2 };

        mesh.RecalculateBounds();
        mesh.RecalculateTangents();

        meshFilter.mesh = mesh;
    }
    #endregion

    #region 画正方形
    void DrawSquare()
    {
        mesh = new Mesh();
        mesh.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0), new Vector3(1, 0, 0) };
        mesh.triangles = new int[]
        { 0, 1, 2,
          0, 2, 3
        };

        mesh.RecalculateBounds();
        mesh.RecalculateTangents();

        meshFilter.mesh = mesh;
    }
    #endregion

    #region 画圆
    /// <summary>
    /// 画圆
    /// </summary>
    /// <param name="radius">圆的半径</param>
    /// <param name="segments">圆的分割数</param>
    /// <param name="centerCircle">圆心得位置</param>
    void DrawCircle(float radius, int segments, Vector3 centerCircle)
    {

        //顶点
        Vector3[] vertices = new Vector3[segments + 1];
        vertices[0] = centerCircle;
        float deltaAngle = Mathf.Deg2Rad * 360f / segments;
        float currentAngle = 0;
        for (int i = 1; i < vertices.Length; i++)
        {
            float cosA = Mathf.Cos(currentAngle);
            float sinA = Mathf.Sin(currentAngle);
            vertices[i] = new Vector3(cosA * radius + centerCircle.x, sinA * radius + centerCircle.y, 0);
            currentAngle += deltaAngle;
        }

        //三角形
        int[] triangles = new int[segments * 3];
        for (int i = 0, j = 1; i < segments * 3 - 3; i += 3, j++)
        {
            triangles[i] = 0;
            triangles[i + 1] = j + 1;
            triangles[i + 2] = j;
        }
        triangles[segments * 3 - 3] = 0;
        triangles[segments * 3 - 2] = 1;
        triangles[segments * 3 - 1] = segments;

        mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateBounds();
        mesh.RecalculateTangents();

        meshFilter.mesh = mesh;
    }
    #endregion

    #region 画圆环
    /// <summary>
    /// 画圆环
    /// </summary>
    /// <param name="radius">圆半径</param>
    /// <param name="innerRadius">内圆半径</param>
    /// <param name="segments">圆的分个数</param>
    /// <param name="centerCircle">圆心坐标</param>
    void DrawRing(float radius, float innerRadius, int segments, Vector3 centerCircle)
    {
        //顶点
        Vector3[] vertices = new Vector3[segments * 2];
        float deltaAngle = Mathf.Deg2Rad * 360f / segments;
        float currentAngle = 0;
        for (int i = 0; i < vertices.Length; i += 2)
        {
            float cosA = Mathf.Cos(currentAngle);
            float sinA = Mathf.Sin(currentAngle);
            vertices[i] = new Vector3(cosA * innerRadius + centerCircle.x, sinA * innerRadius + centerCircle.y, 0);
            vertices[i + 1] = new Vector3(cosA * radius + centerCircle.x, sinA * radius + centerCircle.y, 0);
            currentAngle += deltaAngle;
        }

        //三角形
        int[] triangles = new int[segments * 6];
        for (int i = 0, j = 0; i < segments * 6; i += 6, j += 2)
        {
            triangles[i] = j;
            triangles[i + 1] = (j + 1) % vertices.Length;
            triangles[i + 2] = (j + 3) % vertices.Length;

            triangles[i + 3] = j;
            triangles[i + 4] = (j + 3) % vertices.Length;
            triangles[i + 5] = (j + 2) % vertices.Length;
        }
        mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateBounds();
        mesh.RecalculateTangents();

        meshFilter.mesh = mesh;
    }

    #endregion

    #region 画正方体
    protected void DrawCube(float x, float y, float z)
    {
        var halfX = x / 2;
        var halfY = y / 2;
        var halfZ = z / 2;

        mesh = new Mesh();
        mesh.vertices = new Vector3[]
        {
            new Vector3(-halfX, -halfY, -halfZ),
            new Vector3(halfX, -halfY, -halfZ),
            new Vector3(halfX, halfY, -halfZ),
            new Vector3(-halfX, halfY, -halfZ),
            new Vector3(-halfX, halfY, halfZ),
            new Vector3(halfX, halfY, halfZ),
            new Vector3(halfX, -halfY, halfZ),
            new Vector3(-halfX, -halfY, halfZ),
        };
      
        //设置三角形顶点顺序，顺时针设置
        mesh.triangles = new int[]
        {
          0, 2, 1,
            0,3,2,
            3,4,2,
            4,5,2,
            4,7,5,
            7,6,5,
            7,0,1,
            6,7,1,
            4,3,0,
            4,0,7,
            2,5,6,
            2,6,1

        };

        mesh.RecalculateBounds();
        mesh.RecalculateTangents();

        meshFilter.mesh = mesh;
    }
    #endregion

    #region 圆柱 和 圆环 , 和 扇形
    /// <summary>
    /// 生成圆柱 和 圆环 , 和 扇形
    /// </summary>
    /// <param name="outRadian"></param>
    /// <param name="innerRadian"></param>
    /// <param name="height"></param>
    public void GenerateCircle(float outRadian,float innerRadian,float realAngle, float height)
    {
        float EachAngle;
        EachAngle = 2 * Mathf.PI / details;

        vertices = new List<Vector3>();
        triangles = new List<int>();
        uv = new List<Vector2>();
        normals = new List<Vector3>();

        temp_vertices = new List<Vector3>();

        //计算外侧数据
        int trunc = Mathf.FloorToInt(outRadian / EachAngle);

        realAngle = trunc * EachAngle * Mathf.Rad2Deg;
        for (int i = 0; i <= trunc; i++)
        {
            Vector3 v1 = new Vector3(outRadian * Mathf.Sin(i * EachAngle), 0, outRadian * Mathf.Cos(i * EachAngle));
            Vector3 v2 = new Vector3(outRadian * Mathf.Sin(i * EachAngle), -height, outRadian * Mathf.Cos(i * EachAngle));
            //外侧顶点
            temp_vertices.Add(v1); temp_vertices.Add(v2);
            //外侧顶点UV坐标
            uv.Add(new Vector2(((i * 1.0f) / trunc * 1.0f), 1)); uv.Add(new Vector2(((i * 1.0f) / trunc * 1.0f), 0));
            //外侧顶点法线
            normals.Add((v1 - Vector3.zero).normalized); normals.Add((v2 - new Vector3(0, -height, 0)).normalized);
        }
        vertices.AddRange(temp_vertices);
        //外侧三角形
        for (int i = 0; i < temp_vertices.Count - 2; i += 2)
        {
            triangles.Add(i); triangles.Add(i + 1); triangles.Add(i + 3);
            triangles.Add(i); triangles.Add(i + 3); triangles.Add(i + 2);
        }
        temp_vertices.Clear();

        //计算内侧数据
        for (int i = 0; i <= trunc; i++)
        {
            Vector3 v1 = new Vector3(innerRadian * Mathf.Sin(i * EachAngle), 0, innerRadian * Mathf.Cos(i * EachAngle));
            Vector3 v2 = new Vector3(innerRadian * Mathf.Sin(i * EachAngle), -height, innerRadian * Mathf.Cos(i * EachAngle));
            //内侧顶点
            temp_vertices.Add(v1); temp_vertices.Add(v2);
            //内侧顶点UV坐标
            uv.Add(new Vector2(((i * 1.0f) / trunc * 1.0f), 1)); uv.Add(new Vector2(((i * 1.0f) / trunc * 1.0f), 0));
            //内侧顶点法线
            normals.Add((Vector3.zero - v1).normalized); normals.Add((new Vector3(0, -height, 0) - v2).normalized);
        }
        vertices.AddRange(temp_vertices);
        //内侧三角形
        for (int i = temp_vertices.Count; i < temp_vertices.Count * 2 - 2; i += 2)
        {
            triangles.Add(i); triangles.Add(i + 3); triangles.Add(i + 1);
            triangles.Add(i); triangles.Add(i + 2); triangles.Add(i + 3);
        }
        temp_vertices.Clear();

        //计算顶面数据
        for (int i = 0; i <= trunc; i++)
        {
            Vector3 v1 = new Vector3(innerRadian * Mathf.Sin(i * EachAngle), 0, innerRadian * Mathf.Cos(i * EachAngle));
            Vector3 v2 = new Vector3(outRadian * Mathf.Sin(i * EachAngle), 0, outRadian * Mathf.Cos(i * EachAngle));
            //顶面顶点
            temp_vertices.Add(v1); temp_vertices.Add(v2);
            //顶面顶点UV坐标
            uv.Add((new Vector2(0.5f * Mathf.Sin(i * EachAngle), 0.5f * Mathf.Cos(i * EachAngle)) + new Vector2(0.5f, 0.5f)));
            uv.Add((new Vector2(0.5f * (innerRadian / outRadian) * Mathf.Sin(i * EachAngle), 0.5f * (innerRadian / outRadian) * Mathf.Cos(i * EachAngle)) + new Vector2(0.5f, 0.5f)));
            //顶面顶点法线
            normals.Add(Vector3.up); normals.Add(Vector3.up);

        }
        vertices.AddRange(temp_vertices);
        for (int i = temp_vertices.Count * 2; i < temp_vertices.Count * 3 - 2; i += 2)
        {
            triangles.Add(i); triangles.Add(i + 1); triangles.Add(i + 3);
            triangles.Add(i); triangles.Add(i + 3); triangles.Add(i + 2);
        }
        temp_vertices.Clear();

        //底面数据
        for (int i = 0; i <= trunc; i++)
        {
            Vector3 v1 = new Vector3(innerRadian * Mathf.Sin(i * EachAngle), -height, innerRadian * Mathf.Cos(i * EachAngle));
            Vector3 v2 = new Vector3(outRadian * Mathf.Sin(i * EachAngle), -height, outRadian * Mathf.Cos(i * EachAngle));
            //底面顶点
            temp_vertices.Add(v1); temp_vertices.Add(v2);
            //底面顶点UV坐标
            uv.Add((new Vector2(0.5f * Mathf.Sin(i * EachAngle), 0.5f * Mathf.Cos(i * EachAngle)) + new Vector2(0.5f, 0.5f)));
            uv.Add((new Vector2(0.5f * (innerRadian / outRadian) * Mathf.Sin(i * EachAngle), 0.5f * (innerRadian / outRadian) * Mathf.Cos(i * EachAngle)) + new Vector2(0.5f, 0.5f)));
            //底面法线
            normals.Add(-Vector3.up); normals.Add(-Vector3.up);
        }
        vertices.AddRange(temp_vertices);
        for (int i = temp_vertices.Count * 3; i < temp_vertices.Count * 4 - 2; i += 2)
        {
            triangles.Add(i); triangles.Add(i + 3); triangles.Add(i + 1);
            triangles.Add(i); triangles.Add(i + 2); triangles.Add(i + 3);
        }
        temp_vertices.Clear();
        //封边

        //起点
        Vector3 vs1 = new Vector3(outRadian * Mathf.Sin(0 * EachAngle), 0, outRadian * Mathf.Cos(0 * EachAngle));
        Vector3 vs2 = new Vector3(outRadian * Mathf.Sin(0 * EachAngle), -height, outRadian * Mathf.Cos(0 * EachAngle));
        Vector3 vs3 = new Vector3(innerRadian * Mathf.Sin(0 * EachAngle), 0, innerRadian * Mathf.Cos(0 * EachAngle));
        Vector3 vs4 = new Vector3(innerRadian * Mathf.Sin(0 * EachAngle), -height, innerRadian * Mathf.Cos(0 * EachAngle));
        //顶点
        temp_vertices.Add(vs1); temp_vertices.Add(vs2); temp_vertices.Add(vs3); temp_vertices.Add(vs4);
        // UV
        uv.Add(new Vector2(0, 1)); uv.Add(new Vector2(0, 0)); uv.Add(new Vector2(1, 1)); uv.Add(new Vector2(1, 0));
        //法线
        normals.Add(Vector3.Cross((vs3 - vs1), (vs4 - vs1)).normalized);
        normals.Add(Vector3.Cross((vs3 - vs1), (vs4 - vs1)).normalized);
        normals.Add(Vector3.Cross((vs3 - vs1), (vs4 - vs1)).normalized);
        normals.Add(Vector3.Cross((vs3 - vs1), (vs4 - vs1)).normalized);
        //三角形

        triangles.Add(vertices.Count); triangles.Add(vertices.Count + 3); triangles.Add(vertices.Count + 1);
        triangles.Add(vertices.Count); triangles.Add(vertices.Count + 2); triangles.Add(vertices.Count + 3);
        vertices.AddRange(temp_vertices);
        temp_vertices.Clear();

        //终点
        Vector3 ve1 = new Vector3(outRadian * Mathf.Sin(trunc * EachAngle), 0, outRadian * Mathf.Cos(trunc * EachAngle));
        Vector3 ve2 = new Vector3(outRadian * Mathf.Sin(trunc * EachAngle), -height, outRadian * Mathf.Cos(trunc * EachAngle));
        Vector3 ve3 = new Vector3(innerRadian * Mathf.Sin(trunc * EachAngle), 0, innerRadian * Mathf.Cos(trunc * EachAngle));
        Vector3 ve4 = new Vector3(innerRadian * Mathf.Sin(trunc * EachAngle), -height, innerRadian * Mathf.Cos(trunc * EachAngle));
        //顶点
        temp_vertices.Add(ve1); temp_vertices.Add(ve2); temp_vertices.Add(ve3); temp_vertices.Add(ve4);
        // UV
        uv.Add(new Vector2(0, 1)); uv.Add(new Vector2(0, 0)); uv.Add(new Vector2(1, 1)); uv.Add(new Vector2(1, 0));
        //法线
        normals.Add(Vector3.Cross((ve4 - ve1), (ve3 - ve1)).normalized);
        normals.Add(Vector3.Cross((ve4 - ve1), (ve3 - ve1)).normalized);
        normals.Add(Vector3.Cross((ve4 - ve1), (ve3 - ve1)).normalized);
        normals.Add(Vector3.Cross((ve4 - ve1), (ve3 - ve1)).normalized);
        //三角形
        triangles.Add(vertices.Count); triangles.Add(vertices.Count + 1); triangles.Add(vertices.Count + 3);
        triangles.Add(vertices.Count); triangles.Add(vertices.Count + 3); triangles.Add(vertices.Count + 2);
        vertices.AddRange(temp_vertices);


        mesh = new Mesh();
        mesh.vertices = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.normals = normals.ToArray();
        mesh.uv = uv.ToArray();

        mesh.RecalculateBounds();
        mesh.RecalculateTangents();

        meshFilter.mesh = mesh;

    }
    #endregion
}
